<template>
  <el-main>
    <!-- 查询条件 -->
    <el-form
      :model="searchModel"
      ref="searchForm"
      label-width="80px"
      :inline="true"
      size="small"
    >
      <el-form-item>
        <el-input v-model="searchModel.roleName" placeholder="请输入角色名称"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="search(pageNo,pageSize)">查询</el-button>
        <el-button icon="el-icon-refresh-right" @click="resetValue">重置</el-button>
        <el-button type="success" icon="el-icon-plus" @click="openAddWindow" v-if="hasPermission('sys:role:add')">新增</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据表格 -->
    <el-table
      :data="roleList"
      :height="tableHeight"
      border
      stripe
      style="width:100%;margin-bottom: 10px"
    >
      <el-table-column prop="id" label="角色编号" width="100" align="center"></el-table-column>
      <el-table-column prop="roleName" label="角色名称"></el-table-column>
      <el-table-column prop="remark" label="角色备注"></el-table-column>
      <el-table-column label="操作" align="center" width="290">
        <template slot-scope="scope">
          <el-button type="primary"
            icon="el-icon-edit"
            size="small"
            @click="editRole(scope.row)"
            v-if="hasPermission('sys:role:edit')"
          >
            编辑
          </el-button>
          <el-button type="danger"
            icon="el-icon-delete"
            size="small"
            @click="deleteRole(scope.row)"
            v-if="hasPermission('sys:role:delete')"
          >
            删除
          </el-button>
          <el-button type="primary"
            icon="el-icon-setting"
            size="small"
            @click="assignRole(scope.row)"
            v-if="hasPermission('sys:role:assign')"
          >
            分配权限
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页工具栏 -->
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pageNo"
      :page-sizes="[10,20,30,40,50]"
      :page-size="10"
      :total="total"
      layout="total, sizes, prev, pager, next, jumper"
      background
    >
    </el-pagination>
    <!-- 添加和修改角色窗口 -->
    <system-dialog
      :title="roleDialog.title"
      :visible="roleDialog.visible"
      :width="roleDialog.width"
      :height="roleDialog.height"
      @onClose="onClose"
      @onConfirm="onConfirm"
    >
      <div slot="content">
        <el-form
          :model="role"
          ref="roleForm"
          :rules="rules"
          label-width="80px"
          :inline="false"
          size="small"
        >
          <el-form-item label="角色编码" prop="roleCode">
            <el-input v-model="role.roleCode"></el-input>
          </el-form-item>
          <el-form-item label="角色名称" prop="roleName">
            <el-input v-model="role.roleName"></el-input>
          </el-form-item>
          <el-form-item label="角色描述">
            <el-input v-model="role.remark" type="textarea" :rows="5"></el-input>
          </el-form-item>
        </el-form>
      </div>
    </system-dialog>
    <!-- 分配权限树窗口 -->
    <system-dialog
      :title="assignDialog.title"
      :visible="assignDialog.visible"
      :width="assignDialog.width"
      :height="assignDialog.height"
      @onClose="onAssignClose"
      @onConfirm="onAssignConfirm"
    >
      <div slot="content">
        <el-tree
          ref="assignTree"
          :data="assignTreeData"
          node-key="id"
          :props="defaultProps"
          empty-text="暂无数据"
          :show-checkbox="true"
          :highlight-current="true"
          default-expand-all
        ></el-tree>
      </div>
    </system-dialog>
  </el-main>
</template>

<script>
import { getRoleList,addRole,updateRole,getAssignTreeApi,assignSaveApi,checkRole,deleteRole } from '@/api/role';
//导入对话框组件
import SystemDialog from '@/components/system/SystemDialog.vue';
import hasPermission from '@/permission/index';
//导入末级节点脚本
import leafUtils from '@/utils/leaf';

export default {
  name: 'roleList',
  //注册组件
  components:{
    SystemDialog,
  },
  data(){
    return{
      //分配权限窗口属性
      assignDialog:{
        title:"",
        visible:false,
        height:450,
        width:300,
      },
      roleId:"",//角色Id
      assignTreeData:[],//权限树节点数据
      //树节点属性
      defaultProps:{
        children:"children",
        label:"label",
      },
      //表单校验规则
      rules:{
        roleCode:[{required:true, message:'请输入角色编码', trigger:'blur'}],
        roleName:[{required:true, message:'请输入角色名称', trigger:'blur'}]
      },
      //添加和修改角色窗口属性
      roleDialog:{
        title:"",
        visible:false,
        width:500,
        height:230,
      },
      //角色对象
      role:{
        id:"",
        roleCode:"",
        roleName:"",
        remark:"",
        createUser:this.$store.getters.userId,//用户Id
      },
      //查询条件
      searchModel:{
        roleName:"",
        pageNo:1,
        pageSize:10,
        userId:this.$store.getters.userId,//用户Id
      },
      roleList:[],//角色列表
      tableHeight:0,//表格高度
      pageNo: 1,//当前页码
      pageSize: 10,//每页显示数量
      total: 0,//总记录数
    };
  },
  //初始化时调用
  created(){
    this.search();
  },
  //页面加载时调用
  mounted(){
    this.$nextTick(() => {
      this.tableHeight = window.innerHeight -220;
    })
  },
  methods: {
    /**
     * 打开添加角色窗口
     */
    openAddWindow(){
      //清空表单数据
      this.$resetForm("roleForm", this.role);
      this.roleDialog.title = "新增角色";
      this.roleDialog.visible = true;
    },
    /**
     * 关闭窗口事件
     */
    onClose(){
      this.roleDialog.visible = false;
    },
    /**
     * 确认按钮点击事件
     */
    async onConfirm(){
      this.$refs.roleForm.validate(async (valid) => {
        if(valid){
          let res = null;
          //判断角色Id是否为空
          if(this.role.id === ""){
            res = await addRole(this.role);
          }else {
            res = await updateRole(this.role);
          }
          //判断是否成功
          if(res.success){
            this.$message.success(res.message);
            this.search(this.pageNo, this.pageSize);
            this.roleDialog.visible = false;
          }else{
            this.$message.error(res.message);
          }
        }
      })
    },
    /**
     * 查询
     */
    async search(pageNo=1, pageSize=10){
      this.searchModel.pageNo = pageNo;//当前页码
      this.searchModel.pageSize = pageSize;//每页显示数量
      //发送查询请求
      let res = await getRoleList(this.searchModel);
      if (res.success) {
        this.roleList = res.data.records;
        this.total = res.data.total;
      }
    },
    /**
     * 重置查询条件
     */
    resetValue(){
      //清空查询条件
      this.searchModel.roleName = "";
      //重新查询
      this.search();
    },
    /**
     * 当每页显示数量发生变化时触发该事件
     */
    handleSizeChange(size){
      this.pageSize = size;
      this.search(this.pageNo, size);
    },
    /**
     * 当页码发生变化时触发该事件
     */
    handleCurrentChange(page){
      this.pageNo = page;
      this.search(page, this.pageSize);
    },
    /**
     * 打开编辑角色窗口
     */
    editRole(row){
      //数据回显
      this.$objCopy(row,this.role);
      this.roleDialog.title = "编辑角色";
      this.roleDialog.visible = true;
    },
    /**
     * 删除角色
     */
    async deleteRole(row){
      //查询该角色是否被用户使用
      let res = await checkRole({id:row.id});
      //判断是否可以删除
      if(!res.success){
        this.$message.warning(res.message);
      } else {
        //确认是否可以删除
        let confirm = await this.$confirm("确定要删除该数据吗？");
        if(confirm){
          //发送删除请求
          res = await deleteRole({id:row.id});
          //判断是否成功
          if(res.success){
            this.$message.success(res.message);
            //刷新数据
            this.search(this.pageNo, this.pageSize);
          }else{
            this.$message.error(res.message);
          }
        }
      }
    },
    /**
     * 分配权限
     */
    async assignRole(row){
      //设置角色ID
      this.roleId = row.id;
      //构建参数
      let params = {
        roleId: row.id,
        userId: this.$store.getters.userId,
      }
      //发送查询请求
      let res = await getAssignTreeApi(params);
      //判断是否成功
      if(res.success){
        //获取当前登录用户所拥有的所有权限
        let permissionList = res.data.permissionList;
        //获取当前被分配的角色已经拥有的权限信息
        let checkList = res.data.checkList;
        //判断当前菜单是否是末级
        let {setLeaf} = leafUtils();
        //设置权限菜单列表
        let newPermissionList = setLeaf(permissionList);
        //设置树节点菜单数据
        this.assignTreeData = newPermissionList;
        //将回调延迟到下次DOM更新循环之后执行，在修改数据之后立即使用它，然后等待DOM更新
        this.$nextTick(() => {
          //获取树菜单的节点数据
          let nodes = this.$refs.assignTree.children;
          //设置子节点
          this.setChild(nodes,checkList);
        })
      }
      //显示窗口
      this.assignDialog.visible = true;
      this.assignDialog.title = `给【${row.roleName}】分配权限`;
    },
    /**
     * 设置子节点
     */
    setChild(childNodes,checkList){
      //判断是否存在子节点
      if(childNodes && childNodes.length > 0){
        //循环所有权限
        for(let i=0;i<childNodes.length;i++){
          //根据data或者key拿到Tree组件中的node
          let node = this.$refs.assignTree.getNode(childNodes[i]);
          //判断是否已经拥有对应的角色数据
          if(checkList && checkList.length > 0){
            //循环遍历已有的权限集合
            for(let j=0;j<checkList.length;j++){
              //找到已经存在的菜单权限节点
              if(checkList[j] == childNodes[i].id){
                //如果节点是展开状态，则将树节点选中
                if(childNodes[i].open){
                  this.$refs.assignTree.setChecked(node, true);
                  break;
                }
              }
            }
          }
          //如果存在子节点，则递归选中
          if(childNodes[i].children){
            this.setChild(childNodes[i].children, checkList);
          }
        }
      }
    },
    /**
     * 分配权限窗口关闭事件
     */
    onAssignClose(){
      this.assignDialog.visible = false;
    },
    /**
     * 分配权限窗口确认事件
     */
    async onAssignConfirm(){ 
      //获取选中的节点key
      let ids = this.$refs.assignTree.getCheckedKeys();
      //获取选中节点的父节点id
      let pids = this.$refs.assignTree.getHalfCheckedKeys();
      //组装选中节点的节点id数据
      let listId = ids.concat(pids);
      //组装参数
      let params = {
        roleId: this.roleId,
        list: listId,
      }
      //发送请求
      let res = await assignSaveApi(params);
      //判断是否成功
      if(res.success){
        this.assignDialog.visible = false;
        this.$message.success(res.message);
      }else{
        this.$message.error(res.data);
      }
    },
  },
}
</script>

<style lang="scss" scoped>

</style>